package com.project.comom;

import com.common.api.CommonFileApi;
import com.common.config.RuoYiConfig;
import com.common.constant.Constants;
import com.common.utils.StringUtils;
import com.common.utils.file.FileTypeUtils;
import com.common.utils.file.FileUploadUtils;
import com.common.utils.file.FileUtils;
import com.project.domain.entity.SysUploadFile;
import com.project.mapper.UpLoadFileMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

import static com.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * 通用文件Service
 *
 * @author baige
 * @date 2025-02-24
 */
@Service
public class CommonFileService  implements CommonFileApi {

    @Autowired
    private UpLoadFileMapper fileMapper;

    /**
     * 上传多个文件
     *
     * @param files
     * @param modelName  所属模块 如:zXContract,projectApplyInfo等,一个模块写统一的名称就行
     * @param businessId 正在操作表的主键id,可以为空
     * @return 文件名和文件id的map集合
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public List uploadFiles(List<MultipartFile> files, String modelName, String businessId) throws Exception {
        // 上传文件基础路径
        String filePath = RuoYiConfig.getUploadPath();


        List<Map<String, String>> idList = new ArrayList<>();
        for (MultipartFile file : files) {
            // 上传并返回新文件的保存路径
            String savePath = FileUploadUtils.upload(filePath, file);
            //新文件名
            String newFileName = FileUtils.getName(savePath);
            //原文件名
            String originalFilename = file.getOriginalFilename();
            //文件类型
            String fileType = FileTypeUtils.getFileType(originalFilename);
            //文件大小
            long size = file.getSize();

            SysUploadFile uploadFile = new SysUploadFile();
            uploadFile.setStorageFileName(newFileName);
            uploadFile.setUploadfilename(originalFilename);
            uploadFile.setExtName(fileType);
            uploadFile.setFileSize(size);
            uploadFile.setLastEditDate(new Date());
            uploadFile.setObjectId(businessId);
            uploadFile.setBeanId(modelName);
            uploadFile.setSavePath(savePath);
            int insert = fileMapper.insert(uploadFile);
            if (insert == 1) {
                HashMap<String, String> map = new HashMap<>();
                map.put("id", uploadFile.getId());
                map.put("name", originalFilename);
                idList.add(map);
            }

        }
        return idList;

    }

    /***
     *  上传文件
     * @param file 文件
     * @param modelName  所属模块 所属模块 如:zXContract,projectApplyInfo等,一个模块写统一的名称就行
     * @param businessId  正在操作表的主键id,可以为空
     * @return 文件id
     * @throws Exception
     */
    public String uploadFile(MultipartFile file, String modelName, String businessId) throws Exception {
        // 上传文件基础路径
        String filePath = RuoYiConfig.getUploadPath();
        // 上传并返回新文件的保存路径
        String savePath = FileUploadUtils.upload(filePath, file);
        //新文件名
        String newFileName = FileUtils.getName(savePath);
        //原文件名
        String originalFilename = file.getOriginalFilename();
        //文件类型
        String fileType = FileTypeUtils.getFileType(originalFilename);
        //文件大小
        long size = file.getSize();


        SysUploadFile uploadFile = new SysUploadFile();
        uploadFile.setStorageFileName(newFileName);
        uploadFile.setUploadfilename(originalFilename);
        uploadFile.setExtName(fileType);
        uploadFile.setFileSize(size);
        uploadFile.setLastEditDate(new Date());
        uploadFile.setObjectId(businessId);
        uploadFile.setBeanId(modelName);
        uploadFile.setSavePath(savePath);

        int insert = fileMapper.insert(uploadFile);
        return insert == 1 ? uploadFile.getId() : "";
    }

    /**
     * 下载文件
     *
     * @param fileId   文件id
     * @param response
     * @throws Exception
     */
    public void download(String fileId, HttpServletResponse response)
            throws Exception {
        SysUploadFile uploadFile = fileMapper.selectById(fileId);

        if (uploadFile == null) throw new RuntimeException("资源文件不存在");

        // 本地资源基础路径
        String localPath = RuoYiConfig.getProfile();

        // 本地资源地址完整地址
        String downloadPath = localPath + StringUtils.substringAfter(uploadFile.getSavePath(), Constants.RESOURCE_PREFIX);

     //   String downloadPath = localPath + uploadFile.getSavePath();
        // 下载名称
        String downloadName = uploadFile.getUploadfilename();
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        FileUtils.setAttachmentResponseHeader(response, downloadName);
        FileUtils.writeBytes(downloadPath, response.getOutputStream());

    }

    /**
     * 删除文件
     *
     * @param fileId 文件id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean delFile(String fileId) {
        SysUploadFile uploadFile = fileMapper.selectById(fileId);
        if (uploadFile == null) return false;
        //1.删除数据库记录
        int delDbRecord = fileMapper.deleteById(fileId);
        // 本地资源基础路径
        String localPath = RuoYiConfig.getProfile();
        // 本地资源地址完整地址
//        String downloadPath = localPath + uploadFile.getSavePath();
        String downloadPath = localPath + StringUtils.substringAfter(uploadFile.getSavePath(), Constants.RESOURCE_PREFIX);
        //2.删除
        boolean delFile = FileUtils.deleteFile(downloadPath);
       /* // 文件删除失败，抛出运行时异常触发回滚
        if (!delFile) {
            throw new RuntimeException("删除文件失败");
        }*/

        // 记录日志，避免抛出异常
        if (!delFile) {
            log.warn("文件删除失败，路径：{}", downloadPath);
        }

        return delDbRecord == 1 && delFile;
    }

    @Override
    public String getFileName(String fileId) {
        if (StringUtils.isEmpty(fileId)) return "";
        SysUploadFile uploadFile = fileMapper.selectById(fileId);
        if (uploadFile != null){
            return uploadFile.getUploadfilename();
        }else {
            return "";
        }

    }

    public Boolean fillObjectId(String fileId, String businessId) {
        if (StringUtils.isEmpty(fileId) || StringUtils.isEmpty(businessId))
            return false;
        SysUploadFile file = new SysUploadFile();
        file.setId(fileId);
        file.setObjectId(businessId);
        return fileMapper.updateById(file) > 0;
    }

    /**
     * 获取导出可选属性
     *
     * @param exportType
     * @param proClass
     * @return
     */
    public List<Map<String,String>> getExportStr(String exportType,String proClass) {
        List<Map<String,String>> res = new ArrayList<>();
        String names = "";
        String values = "";
        switch (exportType) {
            case "init": {
                if (proClass.equals("xJProject")) {
                    //校级导出
                    names = "项目编号,项目名称,负责人,批准经费,项目分类,立项日期,所属单位,负责人电话,负责人邮箱,开始日期,计划结项日期,实际结项日期,项目状态," +
                            "经办人,经办人电话,到账金额,成果形式,项目成员,统计归属,一级学科,项目来源,研究类别,社会经济服务目标,国民经济行业,合作单位,备注";
                    values = "code,proName,chargerName,feeAuthorize,projectTypeName,authorizeDate,unitName,chargerPhone,chargerEmail,beginDate,planEndDate,actualEndDate,proStateName," +
                            "transactor,transactorPhone,feeIn,productMode,memberNameList,subClassName,subName,projectTier,resClassName,shjjmbName,gmjjhyName,cooperateName,note";
                } else if (proClass.equals("zXProject")) {
                    //纵向导出
                    names = "批准号,项目编号,项目名称,项目分类,负责人,负责人类型,项目总经费,立项日期,所属单位,项目状态,项目级别,项目成员," +
                            "负责人电话,负责人邮箱,经办人,经办人电话,项目来源单位,学校资助经费,外拨经费,拨款金额,开始日期,计划结项日期,结项日期,成果形式," +
                            "到账率显示信息,执行率显示信息,统计归属,一级学科,研究类别,项目来源,组织形式,社会经济服务目标,国民经济行业,课题类型,课题性质,依托项目名称," +
                            "依托项目负责人,依托项目单位名称,备注";
                    values = "authorizeCode,code,proName,projectTypeName,chargerName,chargerTypeName,feeAuthorizeZx,authorizeDate,unitName,proStateName,proLevelName,memberNameList," +
                            "chargerPhone,chargerEmail,transactor,transactorPhone,projectTier,attachFee,outFee,selfProvideFee,beginDate,planEndDate,actualEndDate,productMode," +
                            "incomeRate,executeRate,subClassName,subName,resClassName,proSourceName,formName,shjjmbName,gmjjhyName,ketiTypeName,natureName,upItemName," +
                            "relyingProjectLeader,relyingProjectUnitName,note";
                } else {
                    //横向导出
                    names = "合同编号,合同名称,负责人,合同经费,合同类别,签订日期,所属单位,项目成员,开始日期,终止日期,负责人类型,负责人电话," +
                            "负责人邮箱,经办人,经办人电话,合同有效状态,进行状态,支付方式,合同是否回收,甲方名称,甲方类型,甲方联系人,甲方联系人电话,甲方所属省份," +
                            "甲方所属地市,甲方地址,甲方邮编,统计归属,一级学科,研究类别,合作形式,项目来源,社会经济服务目标,国民经济行业,审核状态,备注";
                    values = "codeHt,proNameHt,chargerName,feeAuthorizeHt,projectTypeNameHt,authorizeDateHt,unitName,memberNameList,beginDate,planEndDateHt,chargerTypeName,chargerPhone," +
                            "chargerEmail,transactor,transactorPhone,validStateName,proStatusName,payWayName,isRecoverName,buyerName,buyerTypeName,buyerChargerName,buyerTel,areaName," +
                            "cityName,buyerAddress,buyerZipcode,subClassName,subName,resClassName,cooperateName,proSourceName,shjjmbName,gmjjhyName,checkName,note";
                }
                break;
            }
            case "alteration": {
                //项目变更
                names = "项目名称,负责人名称,所属单位,项目分类,变更类型,变更原因,变更时间,被委托人姓名,委托开始日期,委托结束日期";
                values = "projectName,chargerName,unitName,proTypeName,alterTypeName,alterReason,alterDate,mandataryname,mandatarybegindate,mandataryenddate";
                break;
            }
            case "midleCheck": {
                //项目中检
                if (proClass.equals("zXProject")) {
                    names = "项目编号,";
                    values = "proCode,";
                }

                names = names + "项目名称,负责人,所属单位,项目分类,中检说明,中检日期,审核状态";
                values = values + "proName,chargerName,unitName,proTypeName,zjNote,middleCheckDate,checkstatusName";
                break;
            }
            case "complete": {
                //项目结项
                if (proClass.equals("yfContract")) {
                    names = "项目编号,";
                    values = "proCode,";
                }
                if (!proClass.equals("xJProject")) {
                    names = names + "验收类别,";
                    values = values + "acceptTypeName,";
                }

                names = names + "项目名称,负责人,所属单位,项目分类,结项说明,结项日期,审核状态";
                values = values + "proName,chargerName,unitName,proTypeName,jxNote,completeDate,checkstatusName";
                break;
            }
            case "ethical":{
                names = "项目名称,项目负责人,所属单位,申请人,申请时间,联系电话,审核状态";
                values = "name,chargerName,unitName,applyer,applyTime,contactPhone,checkstatusName";
                break;
            }
            case "resServ":{
                names = "服务类型,所属单位,申请人,申请时间,联系电话,审核状态";
                values = "serviceTypeName,unitName,applyer,applyTime,contactPhone,checkstatusName";
                break;
            }
        }

        if (StringUtils.isNotBlank(values) && StringUtils.isNotBlank(names)) {
            String[] nameArray = names.split(",");
            String[] valueArray = values.split(",");
            if(nameArray.length == valueArray.length){
                for(int m = 0;m<nameArray.length;m++){
                    Map<String,String> nameWithValue = new HashMap<>();
                    nameWithValue.put("showName",nameArray[m]);
                    nameWithValue.put("field",valueArray[m]);
                    res.add(nameWithValue);
                }
            }
        }
        return res;
    }
}
